#pragma once

#include "storage_device.h"
#include <mutex>
#include "base_noncopyable.h"

namespace El {
namespace Storage {

class StorageDeviceImpl final : public IStorageDevice {
public:
    static std::shared_ptr<IStorageDevice> CreateStorageDevice(DeviceType type,
                                                               const std::string &devicePath,
                                                               const std::string &mountPath);

    DISALLOW_COPY_AND_MOVE(StorageDeviceImpl);

    explicit StorageDeviceImpl(DeviceType type, std::string devicePath, std::string mountPath);
    ~StorageDeviceImpl() override = default;

    DeviceType GetType() const override;
    std::string GetDevicePath() const override;
    std::string GetMountPoint() const override;
    DeviceStatus GetStatus() const override;
    bool Mount() override;
    bool Unmount() override;
    bool Format(FileSystemType fsType) override;
    StorageCapacity GetCapacity() const override;
    bool Repair() override;
    FileSystemType GetFileSystemType() const override;
    bool CheckFileSystem() override;
    bool Defragment() override;
    FileSystemType DetectFileSystemType();

private:
    static constexpr const char *MOUNT_STATUS_FILE = ".mount_status";
    bool CreateMountStatusFile();
    bool RemoveMountStatusFile();
    bool CheckAndRepairIfNeeded();
    bool RunFsck();

    DeviceType type_;
    std::string devicePath_;
    std::string actualDevicePath_;
    std::string mountPoint_{};
    DeviceStatus status_{DeviceStatus::ERR_UNMOUNTED};
    FileSystemType fileSystemType_{FileSystemType::FAT32};
    bool isMounted_{false};
    mutable std::mutex mutex_;
};

} // namespace Storage
} // namespace El
